"""
@Author : 合肥一元数智教育科技有限公司
@Date :  2025/6/7 10:03
@Description : 
服务端
"""
import socket
import threading
import time

import wx
from wx import Point, Size


class ChatServer(wx.Frame):
    def __init__(self):
        # 初始化服务端socket
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.bind(('127.0.0.1', 9999))
        self.socket.listen(5)
        # 服务器状态标识
        self.is_started = False
        # 存储客户端连接的socket对象
        self.all_client_socket = []
        # 窗口初始化
        self.frame = wx.Frame.__init__(self, None, title='群聊服务器', pos=Point(0, 50), size=Size(450, 550))
        self.panel = wx.Panel(self)
        """
         按钮初始化
         1. 启动服务器
         2. 保存聊天记录
        """
        self.start_server_btn = wx.Button(self.panel, label='启动服务器', pos=Point(10, 10), size=Size(200, 40))
        self.save_message_btn = wx.Button(self.panel, label='保存记录', pos=Point(250, 10), size=Size(200, 40))

        """
          按钮事件绑定
        """
        self.start_server_btn.Bind(wx.EVT_BUTTON, self.start_server)
        self.save_message_btn.Bind(wx.EVT_BUTTON, self.save_message)

        # 创建聊天内容文本框  多行信息和只读
        self.show_text = wx.TextCtrl(self.panel, size=Size(440, 400), pos=Point(10, 60),
                                     style=wx.TE_READONLY | wx.TE_MULTILINE)

    #  启动服务端
    def start_server(self, event):
        if not self.is_started:
            self.is_started = True
            self.show_text.AppendText('服务器启动,等待客户端连接...\n')
            # 创建新线程 将客户端连接的监听 放在子线程中  防止主线程阻塞导致窗口未响应
            threading.Thread(target=self.connect_accept).start()

    # =处理客户端连接
    def connect_accept(self):
        while self.is_started:
            client_socket, client_address = self.socket.accept()
            # 存储客户端socket
            self.all_client_socket.append(client_socket)
            str_message = f'【系统通知】{client_address[0]}:{client_address[1]}进入聊天室...\n'
            self.show_text.AppendText(str_message)
            # 群发进群通知
            for one_socket in self.all_client_socket:
                one_socket.send(str_message.encode('utf-8'))
            # 创建线程处理客户端任务
            threading.Thread(target=self.socket_client_handler, args=(client_socket, client_address)).start()

    # 处理客户端的连接
    def socket_client_handler(self, socket_client, address):
        try:
            while self.is_started:
                message = socket_client.recv(1024).decode('utf-8')
                str_message = f'【{address[0]}:{address[1]}】: {message}\n'
                self.show_text.AppendText(str_message)
                # 群发消息
                for one_socket in self.all_client_socket:
                    one_socket.send(str_message.encode('utf-8'))
        except ConnectionResetError:
            # 剔除下线用户
            self.all_client_socket.remove(socket_client)
            str_message = f'【系统通知】{address[0]}:{address[1]}退出聊天室...\n'
            # 显示用户退出聊天室信息
            self.show_text.AppendText(str_message)
            #  群发用户退出消息
            for one_socket in self.all_client_socket:
                one_socket.send(str_message.encode('utf-8'))

    # 保存记录  获取当前窗口信息
    def save_message(self, event):
        with open('message.txt', 'a+', encoding='utf-8') as f:
            time_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
            f.write(f'*******************{time_str}*************************\n')
            f.write(self.show_text.GetValue())


if __name__ == '__main__':
    app = wx.App()
    chat_server = ChatServer()
    chat_server.Show()
    app.MainLoop()
